# @Time : 2024-10-18 15:07
# @Author : Fioman 
# @Phone : 13149920693
"""
列表list: 有序且可变的集合,允许重复的成员
列表是不同数据类型的集合,有序且可以修改(可变).列表可以为空,也可以包含不同类型的项.
"""
# region 1. 列表创建访问修改和切片
# 1. 创建空列表
emptyList01 = []
emptyList02 = list()
# 2. 访问列表
fruits = ["banana", "apple", "orange", "pear", "mango"]
print(f"第一项: {fruits[0]},最后一项: {fruits[-1]},或者这样访问最后一项:{fruits[len(fruits) - 1]}")
print(f"fruits : {fruits},长度为: {len(fruits)}")
# 3. 修改列表的元素
fruits[0] = "lemon"
print(f"fruits : {fruits},长度为: {len(fruits)}")
# 4. 列表的切片操作
intList = [1, 2, 3, 4, 5]
allList = intList[0:len(intList)]
print("allList = ", allList)
# 或者简为
allList = intList[:]
print("allList = ", allList)
# 获取中间部分,去除首尾
midList = intList[1:len(intList) - 1]
print(f"midList = ", midList)
# 或者也可以采用解包的方式去做
_, *midList, _ = intList
print(f"midList = ", midList)
# 切片其实也是有方向的,其实切片还有一个步长
slicePositive = intList[1:5:1]  # 和 intList[1:2]是等价的,但是后面这个:1是默认的,不能忽略
print(f"slicePositive = ", slicePositive)
slicePositive = intList[::2]  # 假如我这样写2就是步长,获取的就是1,3,5
print(f"slicePositivei = ", slicePositive)
# 假如我们要反向切片呢,比如获取到[5,4,3]这样的
sliecNegtive = intList[-1:-4:-1]  # 最后的-1表示步长,并且是反向的
print(f'sliecNegtive = ', sliecNegtive)
# 注意着正负不能随意的时候,如果是负向的start和end的大小关系应该start > end 比如-1 > -4
# 假如你的start = 1, end = 4 ,你就不能使用步长-1,如果步长是-1也不会报错,但是获取到的是空列表
sliecNegtive = intList[1:4:-1]
print(f"sliecNegtivei = ", sliecNegtive)
# 所以假如我们要让一个列表进行反转,就直接后面用-1就行了,不提供start和end的值默认就是整个列表
reverseList = intList[::-1]
print(f"reverseList = ", reverseList)
# 5. 检索列表项和添加删除列表项
# 判断列表中是否含有某一项
print(f"3 是否在列表中: {3 in intList}")
print(f"apple 是否在水果列表中: {"apple" in fruits}")
# append() 末尾添加元素
intList.append(10)
print(f"10 是否在列表中: {10 in intList}")
# insert(index,data) 特定位置添加元素,在原来的索引index的前面添加一个元素.
# 如果是正值,就相当于是替代了原来的索引位置的值,但是如果是插入的索引是负数,
# 结果又不太一样,就是在原来的索引的前面插入了一个元素了.就不是替代原来的位置的元素了
intList.insert(0, "0")
print(intList)
# insert如果超过了索引呢,超过了索引最大值,就在最后面插入数据
intList.insert(100, "100")
print(intList)
# 如果是负数会出现什么情况呢?如果是负数的话,相当于是插入了倒数第二位的位置了,这是为什么呢?
intList.insert(-1, "1000")  # ['0', 1, 2, 3, 4, 5, 10, '1000', '100']
print(intList)
intList = [1, 2, 3]
intList.insert(-1, -1)  # 为什么呢? 因为其实insert的动作应该是在原来的索引的前面添加一个元素
# 这里原来的元素
print(intList)  # [1, 2, -1, 3]

# remove(item)从列表中删除指定的项,如果item不存在就会报错,所以在移除之前最好是判断一下是否存在
lst = ["item1", "item2", "item3"]
# lst.remove("item10") # 不存在会报错,不建议这么去使用
if "item3" in lst:
    lst.remove("item3")
print("after remove: ", lst)

# pop(index=-1) 删除指定索引(如果未指定索引,则删除最后一项),并且将删除的结果返回
lst = [1, 2, 3, 4, 5, 6]
popVal = lst.pop()
print(f"popVla = {popVal},after pop = {lst}")
# popVal = lst.pop(100) # 如果超过了index会报错
popIndex = 100
if abs(popIndex) < len(lst):
    popVal = lst.pop(popIndex)
else:
    popVal = None
    print(f"{popIndex} 超过了列表的索引范围,列表索引最大值: {len(lst) - 1} ")
print(f"popVal = {popVal},after pop = {lst}")

# 索引可以是负数吗?试一下,应该是可以的,可以是负数
popIndex = -1
if abs(popIndex) < len(lst):
    popVal = lst.pop(popIndex)
else:
    popVal = None
    print(f"{popIndex} 超过了列表的索引范围,列表索引最大值: {len(lst) - 1} ")
print(f"popVal = {popVal},after pop = {lst}")

# 使用Del 删除列表项,可以删除指定索引,也可以删除索引范围内的项,可以可以完全删除列表
lst = [1, 2, 3, 4, 5, 6, 7]
del lst[0]  # 删除第一项
print(f"after del: {lst} ")
del lst[-1]  # 删除最后一项
print(f"after del: {lst}")
del lst[1:3]  # 删除1,2项
print(f"after del: {lst}")
del lst[:]  # 删除整个列表,清空
print(f"after del: {lst}")
lst = [1, 2, 3, 4, 5, 6, 7]
lst1 = lst.copy()
lst2 = lst.copy()
del lst[:]
print(lst)
del lst1[::-1]
print(lst1)
del lst2
# print(lst2)
# 上面这三个删除的效果不一样,最后一个是删除了整个变量,不能访问了,而上面两个和clear()效果一样
# 清空列表项:
lst = [1, 2, 3, 4, 5, 6, 7]
lst.clear()
print("lst after clear: {}".format(lst))
# endregion

# region 2. 列表的连接
# 1) 使用加号 + 连接两个列表
lst1 = [1, 2, 3]
lst2 = ["A", "B", "C"]
lst3 = lst1 + lst2
print("lst after add: {}".format(lst3))
# 2) 使用extend 连接两个列表,和+号的区别是可以直接原地修改列表
lst = [1, 2, 3]
lstAdded = [4, 5, 6, 7, 8, 9]
res = lst.extend(lstAdded)  # 返回None,直接在lst上进行操作
print("lst after extend: {}, extend的返回值 res = {}".format(lst, res))
# endregion

# region 3. 统计列表项 count()
# count() 返回列表中指定项出现的次数
lst = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 1]
count1 = lst.count(1)
count2 = lst.count(2)
count100 = lst.count(100)
print(count1, count2, count100, sep=',')  # 3, 2, 0
# endregion

# region 4. 查找项的索引 index()
# 注意Python的索引查找只有index()方法,不像字符串还有find() rindex() 或者rfind()这些方法
lst = [1, 2, 3, 4, 5, 6]
index1 = lst.index(1)
print("index1 = ", index1)
# 假如要查找的元素不存在,会发生什么,会报错,所以在求索引之前最好是先判断
# 最好的方式来获取索引的方式
indexVal = 100
if indexVal in lst:
    index100 = lst.index(100)
    print("index100 = ", index100)
else:
    print(f"{indexVal} 不在列表中")
# endregion

# region 5. 重复列表 (使用*操作符)
lst = [1, 2, 3]
repeatList = lst * 3
print(lst, repeatList)
# endregion

# region 6.列表反转 reverse() and [::-1]
# 1) 原地操作,reverse()
lst = [1, 2, 3, 4, 5]
lst.reverse()
print("lst afeter reverse: ", lst)
# 2) 通过切片 [::-1]
lst = lst[::-1]
print("lst afeter reverse: ", lst)
# endregion

# region 7. 列表排序 sort(key,reverse) sorted()
# 1) 原地修改
lst = [1, 4, 5, 2, 3, 8, 7, -2, -8, -7]
lst.sort(key=lambda x: abs(x), reverse=True)
print("lst after sort: ", lst)

# 2) 不修改原列表,返回一个结果
lst = [1, 4, 5, 2, 3, 8, 7, -2, -8, -7]
lstSorted = sorted(lst, key=lambda x: x ** 2, reverse=True)
print(f"lst afeter sorted: {lstSorted}")
# endregion

# region 8. 列表推导式 [expression for item in iterable if condition]

# 1) 基本用法,生成1-10的数字列表
numList = [x for x in range(1, 11)]
print(numList)

# 2) 带有条件的列表推导式,生成100以内的偶数数字的平方的列表
numList = [x ** 2 for x in range(1, 101) if x % 2 == 0]
print(numList)

# 3) 嵌套列表推导式
# 生成二维列表(矩阵) 3行五列的矩阵,每一行的内容都是相同的
# 分析一波相当于是生成了3次 [j for j in range(5)] 这个东西也是一个列表[0,1,2,3,4]
# 所以最后的结果就是获取了三个 [0,1,2,3,4]
matrix = [[j for j in range(5)] for i in range(3)]
print(f"matrix = {matrix}")

# 矩阵转置
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(f"transposed = {transposed}")

# 4) 从字符串生成列表
chars = [char for char in "Fioman"]
print(f"chars = {chars}")
# 和使用list()等效
chars = list("Fioman")
print(f"chars = {chars}")
# 但是,使用列表推导式的好处是可以过滤元素,比如过滤掉元音
filterRes = [char for char in "Fioman" if char not in "aeiou"]
print(f"filterRes = {filterRes}")

# 5) 结合函数生成特定列表
lst = [-1, 2, -3, 4]
lstAdded = [abs(x) + x ** 2 for x in lst]
print(f"lstAdded = {lstAdded}")

# 6) 结合enumerate()使用,获取带索引的列表
lst = ["Fioman", "Just", "Fun"]
lstWithIndex = [(index, val) for index, val in enumerate(lst)]
print(f"lstWithIndex = {lstWithIndex}")

# 7) 从多个列表生成组合,多层循环列表推导式
nameList = ["A", "B", "C", "D"]
colorList = ["red", "green", "blue", "gray"]
combinations = [(name, color) for name in nameList for color in colorList]

# 8) 处理复杂数据结果,比如将二维列表,变成1维列表
nestedList = [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]]
flattened = [item for subList in nestedList for item in subList]
print(f"flattened = {flattened}")

# endregion

# region 9. 练习
emptyLst = list()
lst = [1, 2, 3, 4, 5, 6]
print(f"列表长度: {len(lst)}")
firstItem, *midItems, lastItem = lst
print(f"firstItem:{firstItem},midItems:{midItems},lastItem:{lastItem}")
itCompanies = ["FaceBook", "Google", "Microsoft", "Apple", "IBM", "Oracle"]
print(f"itCompanies Original: {itCompanies}")
itCompanies.append("HengDing")
midIndex = len(itCompanies) // 2
itCompanies.insert(midIndex, "HuaWei")
itCompanies[0] = itCompanies[0].upper()
print("itCompanies = ", itCompanies)
jointCompanies = "#".join(itCompanies)
print(f"jointCompanies: {jointCompanies}")
itCompanies.sort()
print(f"itCompanies Sorted: {itCompanies}")
itCompanies.reverse()
itCompanies.sort(reverse=True)
print(f"itCompanies Reversed: {itCompanies}")
firstThree = itCompanies[:3]
print(f"firstThree = {firstThree}")
lastThree = itCompanies[-3:]
print(f"lastThree = {lastThree}")
lstLen = len(itCompanies)
midIndex = lstLen // 2
midCompanies = itCompanies[midIndex - 2:midIndex + 2]
print(f"midCompanies = {midCompanies}")
itCompanies.pop(0)
print(f"itCompanies Popped: {itCompanies}")
del itCompanies[0]
print(f"del itCompanies Popped: {itCompanies}")
midIndex = len(itCompanies) // 2
del itCompanies[midIndex]
print(f"del itCompanies Popped: {itCompanies}")
itCompanies.pop()
print(f"del itCompanies Popped: {itCompanies}")
del itCompanies
frontEnd = ["HTML", "CSS", "JS", "REACT", "Redux"]
backEnd = ["Node", "express", "MongoDb"]
fullStack = frontEnd + backEnd
print("fullStack = ", fullStack)
fullStack.insert(4, "Python")
print(f"fullStack.insert(4,'Python') = {fullStack}")
ages = [19, 22, 19, 24, 20, 25, 26, 24, 25, 24]
agesSorted = sorted(ages)
ageMin = agesSorted[0]
ageMax = agesSorted[-1]
print(agesSorted, f"最小年龄: {ageMin}", f"最大年龄: {ageMax}")
ages.append(ageMin)
ages.append(ageMax)
print("ages after append: {}".format(ages))
agesLen = len(ages)
ages.sort()
if agesLen % 2 == 0:
    midAge = (ages[agesLen // 2 - 1] + ages[agesLen // 2 + 1]) / 2
else:
    midAge = ages[agesLen // 2]
print("midAge = ", midAge)
averAge = sum(ages) / len(ages)
scopeAge = ages[-1] - ages[0]
print(f"averAge = {averAge},scopeAge = {scopeAge}")
print(abs(ages[0] - averAge) > abs(ages[1] - averAge))
# endregion
